#ifndef _NODE_POOL_3D
#define _NODE_POOL_3D

#include "octNode.h"

/*
be able to store node cluster(eight node)


GL_LUMINANCE_ALPHA32UI_EXT 
GL_LUMINANCE_ALPHA_INTEGER_EXT    64bit
GL_UNSIGNED_INT
EXT_gpu_shader4 required


Node Texel structure
1 1 10 10 10 (1 max sub division, 1 node type flag, 10 10 10 nodecluster pointer)

constant color
8 8 8 8 : R G B A

Brick Pointer
2 10 10 10 (2 unused)


*/

//compressed data
struct nodeTexel
{
	unsigned int first;
	unsigned int second;
}typedef;

//meta data
//all the update will be carry out in meta node pool
//the root node is implicit: node pointer is at 0,0,0; block pointer is also at 0,0,0
struct nodeMetaData
{
	int ID;
	unsigned int blockPointer[3];
	unsigned int childrenNodeClusterPointer[3];	
	bool subD;
	bool type;

	//pointer to the tree
	octNode* octNodePointer;//point to the node in the memory
	//time stamp
	float timeStamp;


}typedef;


class nodePool3D
{
public:
	//nodePool contain all the nodes
	nodePool3D(octNode *_root);
	void createNodePoolFromTree(octNode *node, int &count);//recursive construction function
	nodePool3D(int clusterDim);// nodeCluster dimention
	nodePool3D();
	~nodePool3D();

	//meta node
	void setSelfNodeClusterPointer(octNode* node, int &count);
	void createMetaNodePoolFromTree(octNode *node);
	
	//nodeMetaData getNodeMetaDataFromOctNode(octNode* node);
	void setMetaNodeClusterFromOctNode(int z, int y, int x, octNode* node);
	
	void setSingleMetaNode(int z, int y, int x, nodeMetaData metaData);
	nodeMetaData getSingleMetaNode(int z, int y, int x);

	//convert meta data to compressed data;
	void generateCompressedNodePool();
	void generateMetaNodePool();
	nodeTexel convertToCompressedNode(nodeMetaData);
	nodeMetaData convertToMetaDataNode(nodeTexel);



	//Compressed node
	void setNodeTexel(int z, int y, int x,nodeTexel);
	nodeTexel getNodeTexel(int z, int y, int x);
	//void setNodeCluster(int z, int y, int x, nodeCluster nc);// z, y, x is nodeCluster location
	//nodeCluster getNodeCluster(int z, int y, int x);

	//void updateNodePointer();

	//test function
	static void getNodePos(nodeTexel , unsigned int &z, unsigned int &y, unsigned int &x );
	static void getBlockPos(nodeTexel , unsigned int &z, unsigned int &y, unsigned int &x );
	static void getRGBA(nodeTexel , int &R, int &G, int &B, int &A );
	static void getSingleValue(nodeTexel, unsigned int &value);
	static void getMaxSubDivision(nodeTexel , bool &subD);
	static void getNodeTypeFlag(nodeTexel , bool &flag);
	//set 
	static void setBlockNodeTexel(nodeTexel &node, bool subD, unsigned int nz, unsigned int ny, unsigned int nx, unsigned int bz, unsigned int by, unsigned int bx);
	static void setSingleColorNodeTexel(nodeTexel &node, bool subD, int nz, int ny, int nx, int R, int G, int B, int A);
	static void setSingleColorNodeTexel(nodeTexel &node, bool subD, unsigned int nz, unsigned int ny, unsigned int nx, unsigned int singleValue);

	void setNodePos(nodeTexel &node, int z, int y, int  x);
	void setBlockPos(nodeTexel &node, int z, int y, int  x);
	void setRGBA(nodeTexel &node, int R, int G, int B, int A );
	void setMaxSubDivision(nodeTexel &node, int subD);
	void setNodeTypeFlag(nodeTexel &node, int flag);

	//write to file
	bool writeToFile(const char* filename);
	bool readCompressedPoolFromFile(const char*filename, int dim);

	//debug
	void debugOutput();
	void debugOutputToFile(const char* filename);

private:
	int _dim;
	nodeTexel *_data;

	nodeMetaData *_metaData;


	//debug
	int _count;
	

};

#endif